package com.liangxiao.wifichat;

import android.net.DhcpInfo;
import android.net.wifi.*;
import android.content.*;

import java.lang.reflect.*;

import android.util.Log;
import com.liangxiao.wifichat.util.*;

import java.util.*;
import java.io.*;

import android.net.*;

public class WifiApManager {
    private final String TAG = "WifiApManager";
    private WifiManager wifi = null;
    /**
     * ap热点旧的配置信息，可用于恢复AP配置
     */
    private WifiConfiguration oldConfig;
    private Context mContext;
    private int currentNetID = -1;
    private ConnectivityManager mConnectivityManager;

    public final int WIFI_AP_STATE_DISABLING = 10;
    public final int WIFI_AP_STATE_DISABLED = 11;
    public final int WIFI_AP_STATE_ENABLING = 12;
    public final int WIFI_AP_STATE_ENABLED = 13;
    public final int WIFI_AP_STATE_FAILED = 14;

    public final int WIFI_CONNECT_STATE_FAILED = 0;
    public final int WIFI_CONNECT_STATE_CONNECTING = 1;
    public final int WIFI_CONNECT_STATE_CONNECTED = 2;

    public static final String DEFAULT_PASSWORD = "123456789";
    public static final String DEFAULT_SSID_PREFIX = "WifiChat-";

    public WifiApManager(Context context) {
        wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        oldConfig = getWifiApConfiguration();
        mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        mContext = context;

    }

    public boolean isWifiApEnabled() {
        Method method = reflect("isWifiApEnabled");
        try {
            return (Boolean) method.invoke(wifi);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public boolean setWifiApEnabled(WifiConfiguration config, boolean isEnabled) {
        try {
            setWifiApConfiguration(config);
            Method m = reflect("setWifiApEnabled", WifiConfiguration.class, boolean.class);
            return (Boolean) m.invoke(wifi, config, isEnabled);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    public WifiConfiguration getWifiApConfiguration() {
        try {
            Method m = reflect("getWifiApConfiguration");
            return (WifiConfiguration) m.invoke(wifi);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public boolean setWifiApConfiguration(WifiConfiguration config) {
        try {
            Method m = reflect("setWifiApConfiguration", WifiConfiguration.class);
            return (Boolean) m.invoke(wifi, config);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public boolean isWifiEnabled() {
        return wifi.isWifiEnabled();
    }

    public int getWifiApState() {
        try {
            Method m = reflect("getWifiApState");
            return (Integer) m.invoke(wifi);
        } catch (Exception e) {
            e.printStackTrace();
            return WIFI_AP_STATE_FAILED;
        }
    }

    public boolean closeWifi() {
        int state = wifi.getWifiState();
        if (state == WifiManager.WIFI_STATE_ENABLED || state == WifiManager.WIFI_STATE_ENABLING) {
            return wifi.setWifiEnabled(false);
        }
        return true;
    }

    public boolean connect(String ssid, String password) {
        Log.d(TAG, "正在连接wifi，ssid=" + ssid + " pwd=" + password);
        if (StringUtils.isEmpty(ssid) && StringUtils.isEmpty(password)) {
            throw new IllegalArgumentException("名称或密码不能为空");
        }
        //打开WIFI
        if (!wifi.isWifiEnabled()) {
            if (!wifi.setWifiEnabled(true)) {
                Log.d(TAG, "wifi打开失败");
                return false;
            }
        }

        WifiConfiguration config = createDefultConguration(ssid, password, false);

        config.status = WifiConfiguration.Status.DISABLED;
        if (!removeIfEixsted(ssid)) {
            Log.d(TAG, "wifi移除失败");
            return false;
        }
        int netID = wifi.addNetwork(config);
        boolean result = wifi.enableNetwork(netID, true);
        currentNetID = netID;
        Log.d(TAG, "WIFI enabledNetWork: " + netID + " result:" + result);

        //result = wifi.reconnect();
        //Log.d(TAG,"wifi reconnect() "+result);
        return result;
    }

    public boolean openAP() {
        return openAP(null, null);
    }

    public boolean openAP(String ssid, String password) throws IllegalArgumentException {
        Log.d(TAG, "正在打开AP，ssid=" + ssid + " pwd=" + password);
        closeWifi();//打开AP前需要关闭wifi
        closeAp(false);//关闭AP
        if (StringUtils.isNotEmpty(password) && password.length() < 8) {
            throw new IllegalArgumentException("密码长度不能小于8位");
        }

        if (StringUtils.isEmpty(ssid) && StringUtils.isEmpty(password)) {
            return setWifiApEnabled(null, true);

        } else {
            WifiConfiguration config = createDefultConguration(ssid, password, true);
            boolean b = setWifiApEnabled(config, true);
            return b;
        }
    }

    public boolean closeAp(boolean reset) {
        Log.d(TAG, "关闭AP，是否复位 " + reset);
        int state = getWifiApState();
        if (state == WIFI_AP_STATE_ENABLED || state == WIFI_AP_STATE_ENABLING) {
            return setWifiApEnabled(reset ? oldConfig : null, false);
        }
        return true;
    }

    public boolean resetAp() {
        Log.d(TAG, "恢复AP设置");
        if (oldConfig != null) {
            return setWifiApConfiguration(oldConfig);
        }
        return false;
    }

    //TODO 获取本地IP地址 例如192.168.43.1
    public String getLocalIpAdress() {
        String ipAdress = "null";
        if (isWifiApEnabled()) {
            Log.d(TAG, "本机为WiFi热点，返回默认IP 192.168.43.1");
            ipAdress = "192.168.43.1";
        } else {
            WifiInfo info = wifi.getConnectionInfo();
            if (info != null) {
                int ip = info.getIpAddress();
                ipAdress = intToIp(ip);
            }
        }
        Log.d(TAG, "获取本地IP " + ipAdress);
        return ipAdress;
    }

    public String getServerIpAdress() {
        String ipAdress = "null";
        DhcpInfo info = wifi.getDhcpInfo();
        if (info != null) {
            int ip = info.serverAddress;
            ipAdress = intToIp(ip);
        }
        Log.d(TAG, "获取服务器ip " + ipAdress);
        return ipAdress;
    }

    public List<String> getConnectedIP() {
        List<String> list = new ArrayList<>();
        try {
            BufferedReader br = new BufferedReader(new FileReader("/proc/net/arp"));
            String line;
            while ((line = br.readLine()) != null) {
                String[] data = line.split(" + ");
                if (data != null && data.length >= 4) {
                    list.add(data[0]);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        Log.d(TAG, "获取已连接 ip ,数量 : " + list.size());
        return list;
    }

    public int getWifiConnectState() {
        NetworkInfo info = mConnectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
        if (info == null) {
            Log.i(TAG, "isWifiConnected() 错误");
            return WIFI_CONNECT_STATE_FAILED;
        }
        if (!info.isConnectedOrConnecting()) {
            Log.d(TAG, "wifi 处于非连接状态");
            return WIFI_CONNECT_STATE_FAILED;
        }
        if (info.getDetailedState() == NetworkInfo.DetailedState.CONNECTED) {
            Log.d(TAG, "WiFi已连接");
            return WIFI_CONNECT_STATE_CONNECTED;
        } else if (info.getDetailedState() == NetworkInfo.DetailedState.CONNECTING) {
            Log.d(TAG, "WiFi正在连接");
            return WIFI_CONNECT_STATE_CONNECTING;
        }
        return WIFI_CONNECT_STATE_FAILED;


    }

    public boolean disConnect() {
        int state = getWifiConnectState();
        if (state != WIFI_CONNECT_STATE_FAILED) {
            if (currentNetID != -1) {
                wifi.disableNetwork(currentNetID);
                return wifi.disconnect();
            }
        }
        return false;
    }

    public WifiManager getWifiManager() {
        return wifi;
    }

    public WifiConfiguration getOldWifiConguration() {
        return oldConfig;
    }

    private String intToIp(int paramIntip) {
        return (paramIntip & 0xFF) + "." + ((paramIntip >> 8) & 0xFF) + "."
                + ((paramIntip >> 16) & 0xFF) + "." + ((paramIntip >> 24) & 0xFF);
    }

    private boolean removeIfEixsted(String ssid) {
        List<WifiConfiguration> list = wifi.getConfiguredNetworks();
		Log.d(TAG,"removeIfExixsted() ssid "+ ssid+" list size "+list.size());
        if (list == null) {
            return true;
        }
        for (WifiConfiguration config : list) {
			Log.d(TAG,config.SSID);
            if (config.SSID.equals("\""+DEFAULT_SSID_PREFIX+ssid+"\"")) {
				Log.d(TAG,"网络 "+ssid+ " 已存在，正在移除");
                return wifi.removeNetwork(config.networkId);
            }
        }
        return true;
    }

    private WifiConfiguration createDefultConguration(String ssid, String password, boolean isServer) {
        WifiConfiguration config = new WifiConfiguration();
        if (StringUtils.isNotEmpty(ssid)) {
            if (isServer) {
                config.SSID = DEFAULT_SSID_PREFIX + ssid;
            } else {
                config.SSID = "\"" + DEFAULT_SSID_PREFIX + ssid + "\"";
            }
        } else {
            config.SSID = oldConfig.SSID;
        }
        if (StringUtils.isNotEmpty(password)) {
            if (isServer) {
                config.preSharedKey = password;
            } else {
                config.preSharedKey = "\"" + password + "\"";
            }

        } else {
            config.preSharedKey = "\"" + DEFAULT_PASSWORD + "\"";
        }
        /*config.allowedAuthAlgorithms.clear();
        config.allowedGroupCiphers.clear();
        config.allowedKeyManagement.clear();
        config.allowedPairwiseCiphers.clear();
        config.allowedProtocols.clear();*/

        config.hiddenSSID = true;
        //config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
        config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
        config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
        //config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);

        config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
        config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
        config.status = WifiConfiguration.Status.ENABLED;
        return config;
    }

    private Method reflect(String name, Class<?>... params) {
        try {
            Method method = WifiManager.class.getMethod(name, params);
            return method;
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
            return null;
        }

    }
}
